﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PayloadTracker.APRS.Parsers
{
    [ParserName("NMEA Parser")]
    class NMEA : IParser
    {
        GPGGA m_GPGGA;
        GPRMC m_GPRMC;
        GPGSV m_GPGSV;
        GPGSA m_GPGSA;

        APRSBeacon m_Partial;
        public NMEA()
        {
            m_GPGGA = new GPGGA();
            m_GPRMC = new GPRMC();
            m_GPGSV = new GPGSV();
            m_GPGSA = new GPGSA();

            m_Partial = null;

        }
        public override APRSBeacon Parse(string sentence)
        {

            if (!IsValidSentence(sentence))
                throw new Exception("Unparsed Sentence");

            if (m_Partial == null)
            {
                if (m_GPGGA.IsValidSentence(sentence))
                    m_Partial = m_GPGGA.Parse(sentence);
                else if (m_GPRMC.IsValidSentence(sentence))
                    m_Partial = m_GPRMC.Parse(sentence);
                else if (m_GPGSV.IsValidSentence(sentence))
                    m_Partial = m_GPGSV.Parse(sentence);
                else if (m_GPGSA.IsValidSentence(sentence))
                    m_Partial = m_GPGSA.Parse(sentence);
                return null;
            }
            else
            {

                if (m_GPGGA.IsValidSentence(sentence))
                {
                    var part = m_GPGGA.Parse(sentence);
                    m_Partial.Time = part.Time;
                    m_Partial.Position = part.Position;
                    m_Partial.Altitude = part.Altitude;
                }
                else if (m_GPRMC.IsValidSentence(sentence))
                {
                    var part = m_GPRMC.Parse(sentence);
                    m_Partial.Course = part.Course;
                    m_Partial.Speed = part.Speed;
                }
                else if (m_GPGSV.IsValidSentence(sentence))
                {
                    var sv = m_GPGSV.ParseSV(sentence);
                    if (sv != null)
                    {
                        //TODO: do something about satellite data
                    }
                }
                else if (m_GPGSA.IsValidSentence(sentence))
                {
                    var dop = m_GPGSA.ParseDOP(sentence);
                    if (dop != null)
                    {
                        //TODO: do something about DOP data
                    }
                }
                
                APRSBeacon ret = m_Partial;
                
                //HACK: Make this configurable through SOMETHING.
                m_Partial.Callsign = "GPS";
                m_Partial = null;
                return ret;
            }
        }

        public override bool IsValidSentence(string sentence)
        {
            return m_GPRMC.IsValidSentence(sentence) 
                || m_GPGGA.IsValidSentence(sentence) 
                || m_GPGSV.IsValidSentence(sentence)
                || m_GPGSA.IsValidSentence(sentence);
        }
    }
}
